﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;

namespace Elderos.Dialogs
{
    /// <summary>
    /// Interaction logic for MsgBox.xaml
    /// </summary>
    public sealed partial class MsgBox : Window
    {
        public MsgBox()
        {
            InitializeComponent();
        }

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }



        public ImageSource Image
        {
            get { return (ImageSource)GetValue(ImageProperty); }
            set
            {
                if (value == null)
                {
                    Grid.SetColumn(TextGrid, 0);
                    Grid.SetColumnSpan(TextGrid, 2);
                }
                else
                {
                    Grid.SetColumn(TextGrid, 1);
                    Grid.SetColumnSpan(TextGrid, 1);
                }
                SetValue(ImageProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for Image.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ImageProperty =
            DependencyProperty.Register("Image", typeof(ImageSource), typeof(MsgBox), new UIPropertyMetadata(null));


        // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register("Text", typeof(string), typeof(MsgBox), new UIPropertyMetadata(null));

        public string Caption
        {
            get { return (string)GetValue(CaptionProperty); }
            set
            {
                if (value == null)
                {
                    Grid.SetRow(MessageBlock, 0);
                    Grid.SetRowSpan(MessageBlock, 2);
                    MessageBlock.Margin = new Thickness(10, 10, 10, 0);
                }
                else
                {
                    Grid.SetRow(MessageBlock, 1);
                    Grid.SetRowSpan(MessageBlock, 1);
                    MessageBlock.Margin = new Thickness(20, 0, 10, 10);
                }
                SetValue(CaptionProperty, value);
            }
        }

        // Using a DependencyProperty as the backing store for Caption.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CaptionProperty =
            DependencyProperty.Register("Caption", typeof(string), typeof(MsgBox), new UIPropertyMetadata(null));

        private MsgBoxButtons _buttons;

        private readonly object _msgBoxButtonsLocker = new object();

        public MsgBoxButtons Buttons
        {
            get { return _buttons; }
            set
            {
                lock (_msgBoxButtonsLocker)
                {
                    _buttons = value;
                    RefreshButtons();
                }
            }
        }

        private void RefreshButtons()
        {
            ButtonPanel.Children.Clear();
            foreach (Button button in GetButtons(Buttons))
            {
                ButtonPanel.Children.Add(button);
            }

            this.MinWidth = ButtonPanel.Children.OfType<Button>().Sum(x => x.Width + x.Margin.Left + x.Margin.Right) + 10;
        }

        public DialogResponse DialogResponse { get; private set; }

        public static DialogResponse Show(string message, string caption = null, string title = null, 
            MsgBoxButtons buttons = MsgBoxButtons.Ok, BitmapSource image = null,
            Window owner = null)
        {
            if (title == null)
                title = "";

            if (owner == null)
            {
                owner = Application.Current.Windows.Cast<Window>().FirstOrDefault(x => x.IsActive);
                owner = owner ?? Application.Current.MainWindow;
            }

            var msgBox =
                new MsgBox
                    {
                        Caption = caption,
                        Text = message,
                        Buttons = buttons,
                        Title = title,
                        Image = image,
                        Owner = owner
                    };

            msgBox.ShowDialog();
            return msgBox.DialogResponse;
        }


        private IEnumerable<Button> GetButtons(MsgBoxButtons buttons)
        {
            if ((buttons & MsgBoxButtons.Ok) == MsgBoxButtons.Ok)
            {
                Button button = ButtonsGenerator.Ok;
                button.Click += (sender, args) =>
                                    {
                                        this.DialogResult = true;
                                        this.DialogResponse = DialogResponse.Yes;
                                        Close();
                                    };
                yield return button;
            }
            if ((buttons & MsgBoxButtons.Yes) == MsgBoxButtons.Yes)
            {
                Button button = ButtonsGenerator.Yes;
                button.Click += 
                    (sender, args) =>
                    {
                        this.DialogResult = true;
                        this.DialogResponse = DialogResponse.Yes;
                        Close();
                    };
                yield return button;
            }
            if ((buttons & MsgBoxButtons.No) == MsgBoxButtons.No)
            {
                Button button = ButtonsGenerator.No;
                button.Click += (sender, args) =>
                {
                    this.DialogResult = true;
                    this.DialogResponse = DialogResponse.No;
                    Close();
                };
                yield return button;
            }
            if ((buttons & MsgBoxButtons.Cancel) == MsgBoxButtons.Cancel)
            {
                Button button = ButtonsGenerator.Cancel;
                button.Click += (sender, args) =>
                {
                    this.DialogResult = false;
                    this.DialogResponse = DialogResponse.None;
                    Close();
                };
                yield return button;
            }
        }

        private static class ButtonsGenerator
        {
            private const int CommonWidth = 60;
            private static readonly Thickness CommonMargin = new Thickness(0, 0, 5, 5);

            private static Button CreateButton(string text)
            {
                var button =
                    new Button
                        {
                            Width = CommonWidth,
                            Content = text,
                            Margin = CommonMargin
                        };
                return button;
            }

            public static Button Ok
            {
                get
                {
                    Button btn = CreateButton("OK");
                    btn.IsDefault = true;
                    return btn;
                }
            }

            public static Button Cancel
            {
                get
                {
                    Button btn = CreateButton("Cancel");
                    btn.IsCancel = true;
                    return btn;
                }
            }

            public static Button Yes
            {
                get
                {
                    Button btn = CreateButton("Yes");
                    btn.IsDefault = true;
                    return btn;
                }
            }

            public static Button No
            {
                get
                {
                    return CreateButton("No");
                }
            }
        }
    }
}
